/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.lcp;


import com.inspur.edp.bef.api.be.BEInfo;
import com.inspur.edp.bef.api.be.IBEManager;
import com.inspur.edp.bef.api.exceptions.BefEngineException;
import com.inspur.edp.bef.api.exceptions.BefException;
import com.inspur.edp.bef.api.exceptions.BizMessageException;
import com.inspur.edp.bef.api.exceptions.ErrorCodes;
import com.inspur.edp.bef.api.lcp.BefContext;
import com.inspur.edp.bef.api.lcp.BefTempTableContext;
import com.inspur.edp.bef.api.lcp.IStandardLcp;
import com.inspur.edp.bef.api.lcp.ResponseContext;
import com.inspur.edp.bef.api.lcp.StandardLcpParam;
import com.inspur.edp.bef.api.parameter.clone.CloneParameter;
import com.inspur.edp.bef.api.parameter.retrieve.RequestedBufferType;
import com.inspur.edp.bef.api.parameter.retrieve.RespectiveRetrieveResult;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveChildResult;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveParam;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveResult;
import com.inspur.edp.bef.api.parameter.save.SaveParameter;
import com.inspur.edp.bef.core.DotNetToJavaStringHelper;
import com.inspur.edp.bef.core.action.base.ActionStack;
import com.inspur.edp.bef.core.action.base.ActionUtil;
import com.inspur.edp.bef.core.action.save.ILcpSaveAction;
import com.inspur.edp.bef.core.be.BEManager;
import com.inspur.edp.bef.core.be.BusinessEntity;
import com.inspur.edp.bef.core.session.BEFuncSessionBase;
import com.inspur.edp.bef.core.session.FuncSession;
import com.inspur.edp.bef.core.session.FuncSessionManager;
import com.inspur.edp.bef.core.session.transaction.BufferTransactionManager;
import com.inspur.edp.bef.core.tcc.BefTccParamItem;
import com.inspur.edp.bef.entity.exception.ExceptionLevel;
import com.inspur.edp.bef.spi.entity.builtinimpls.BefEntityResInfoImpl;
import com.inspur.edp.bef.spi.entity.builtinimpls.BefModelResInfoImpl;
import com.inspur.edp.bef.spi.extend.IBEManagerExtend;
import com.inspur.edp.caf.transaction.api.annoation.tcc.BusinessActionContext;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.action.EditResult;
import com.inspur.edp.cef.api.message.BizMessage;
import com.inspur.edp.cef.api.message.IBizMessage;
import com.inspur.edp.cef.api.message.MessageLevel;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import com.inspur.edp.cef.entity.changeset.ModifyChangeDetail;
import com.inspur.edp.cef.entity.condition.EntityFilter;
import com.inspur.edp.cef.entity.condition.FilterCondition;
import com.inspur.edp.cef.entity.dependenceTemp.DataValidator;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.spi.entity.resourceInfo.EntityResInfo;
import com.inspur.edp.cef.spi.entity.resourceInfo.ModelResInfo;
import com.inspur.edp.cef.variable.api.data.IVariableData;
import com.inspur.edp.commonmodel.api.ICMManager;
import com.inspur.edp.commonmodel.core.session.distributed.SessionEditToken;
import io.iec.edp.caf.commons.exception.CAFRuntimeException;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

@Slf4j
public abstract class StandardLcp implements IStandardLcp {
	private StandardLcpParam param = new StandardLcpParam();

	//region Constructor & Session
	@Deprecated
	protected StandardLcp(String sessionID) {
		//if (string.isNullOrEmpty(sessionID)==false)
		//{
		//    FuncSessionManager.CurrentFuncSessionId = sessionID;
		//}
		//initSession();
	}

	protected StandardLcp() {

	}

	public final void initSession() {
		currentSession = FuncSessionManager.getCurrentSession();
		if (currentSession == null) {
			throwNoSession();
		}
		sessionItem = (BEFuncSessionBase) currentSession.getSessionItems().get(getBEType());
		if (sessionItem == null) {
			currentSession.getSessionItems()
					.put(getBEType(), sessionItem = createSessionItem(currentSession));
		}
	}

	private static void throwNoSession() {
		throw new BefEngineException(ErrorCodes.SessionNotExists, "session不存在, 请先创建BefSession", null);
	}

	@Getter
	private FuncSession currentSession;

	public void setCurrentSession(FuncSession value) {
		Objects.requireNonNull(value);
		if(currentSession != null) {
			throw new RuntimeException();
		}
		currentSession = value;
	}

	private BEFuncSessionBase sessionItem;

	public void initExtends() {
		List<IBEManagerExtend> exts = getExtends();
		if (exts == null) {
			return;
		}
		exts.stream().forEach(item -> addExtend(item));
	}

	protected List<IBEManagerExtend> getExtends() {
		return null;
	}
	//endregion Constructor


	//region 字段属性

	@Override
	public final ResponseContext getResponseContext() {
		return sessionItem == null ? null : sessionItem.getResponseContext();
	}
	//private set { FuncSessionManager.getCurrentSession().ResponseContext = value; }

	private com.inspur.edp.bef.api.lcp.BefContext befContext;

	@Override
	public BefContext getBefContext() {
		return currentSession == null ? (befContext != null) ? befContext
				: (befContext = new BefContext()) : currentSession.getBefContext();
	}

	//endregion 字段属性

	/** 增 */
	@Override
	public final IEntityData retrieveDefault() {
//		try {
		return getBEManager().retrieveDefault();
//		} catch (RuntimeException e) {
//			throw buildBefException("RetrieveDefault", e);
//		}
	}

	@Override
	public final IEntityData retrieveDefault(String dataID) {
//		try {
		return getBEManager().retrieveDefault(dataID);
//		} catch (RuntimeException e) {
//			throw buildBefException("RetrieveDefault", e);
//		}
	}
	@Override
	public final IEntityData retrieveDefault(String dataID,Map<String,Object> defaultValues) {
//		try {
		return getBEManager().retrieveDefault(dataID,defaultValues);
//		} catch (RuntimeException e) {
//			throw buildBefException("RetrieveDefault", e);
//		}
	}
	/**
	 * 复制指定数据
	 * @param cloneDataID 被复制数据id
	 * @return
	 */
	public IEntityData clone(String cloneDataID, CloneParameter cloneParameter){
		return clone(cloneDataID, "", cloneParameter);
	}

	public IEntityData clone(String cloneDataID, String dataID, CloneParameter cloneParameter){
		return getBEManager().clone(cloneDataID, dataID, cloneParameter);
	}

	@Override
	public Map<String, IEntityData> retrieveDefault(List<String> dataIDs) {
		return getBEManager().retrieveDefault(dataIDs);
	}

	/**
	 * 增, 可自定义除主键字段外的默认值
	 */
	@Override
	public final IEntityData retrieveDefault(java.util.Map<String, Object> defaultValues) {
//		try {
		return getBEManager().retrieveDefault(defaultValues);
//		} catch (RuntimeException e) {
//			throw buildBefException("RetrieveDefault", e);
//		}
	}

	/**
	 * 新增业务实体的从(从)表数据
	 * 1. 新增从表数据时，nodeCodes包含从表实体编号，hierachyIdList包含主表数据的唯一标识；
	 * 2. 该方法不只支持新增从表数据，同样的也可以新增从从表数据。新增从从表数据时，
	 * nodeCodes中要包含从从表所属的从表实体编号，以及从从表的实体编号；
	 * hierachyIdList列表包括对应主表数据的唯一标识、子表数据的唯一标识。
	 *
	 * @param nodeCodes      要新增数据的从(从)表的实体编号
	 * @param hierachyIdList 新增从(从)表数据的所属实体数据的唯一标识
	 * @return 新增的从(从)表实体数据
	 */
	@Override
	public final IEntityData retrieveDefaultChild(java.util.List<String> nodeCodes, java.util.List<String> hierachyIdList) {
//		try {
		return getBEManager().retrieveDefaultChild(nodeCodes, hierachyIdList);
//		} catch (RuntimeException e) {
//			throw buildBefException("RetrieveDefaultChild", e);
//		}
	}

	/**
	 * 新增业务实体的从(从)表数据
	 * 1. 新增从表数据时，nodeCodes包含从表实体编号，hierachyIdList包含主表数据的唯一标识；
	 * 2. 该方法不只支持新增从表数据，同样的也可以新增从从表数据。新增从从表数据时，
	 * nodeCodes中要包含从从表所属的从表实体编号，以及从从表的实体编号；
	 * hierachyIdList列表包括对应主表数据的唯一标识、子表数据的唯一标识。
	 *
	 * @param nodeCodes      要新增数据的从(从)表的实体编号
	 * @param hierachyIdList 新增从(从)表数据的所属实体数据的唯一标识
	 * @return 新增的从(从)表实体数据
	 */
	@Override
	public final IEntityData retrieveDefaultChild(java.util.List<String> nodeCodes, java.util.List<String> hierachyIdList, String dataID) {
//		try {
		return getBEManager().retrieveDefaultChild(nodeCodes, hierachyIdList, dataID);
//		} catch (RuntimeException e) {
//			throw buildBefException("RetrieveDefaultChild", e);
//		}
	}

	@Override
	public final IEntityData retrieveDefaultChild(java.util.List<String> nodeCodes, java.util.List<String> hierachyIdList, Map<String, Object> values) {
//		try {
		return getBEManager().retrieveDefaultChild(nodeCodes, hierachyIdList, values);
//		} catch (RuntimeException e) {
//			throw buildBefException("RetrieveDefaultChild", e);
//		}
	}

	@Override
	public final Map<String, IEntityData> retrieveDefaultChild(java.util.List<String> nodeCodes,
															   java.util.List<String> hierachyIdList, List<String> dataIDs) {
		return getBEManager().retrieveDefaultChild(nodeCodes, hierachyIdList, dataIDs);
	}

	@Override
	public final IEntityData createObjectData() {
//		try {
		return innerCreateBeManager().createObjectData();
//		} catch (RuntimeException e) {
//			throw buildBefException("CreateObjectData", e);
//		}
	}

	/**
	 * 删
	 */
	@Override
	public final void delete(java.util.List<String> dataIds) {
//		try {
		DataValidator.checkForNullReference(dataIds, "dataIds");
		getBEManager().delete(dataIds);
//		} catch (RuntimeException e) {
//			throw buildBefException("Delete", e);
//		}
	}

	@Override
	public final void delete(String dataId) {
//		try {
		DataValidator.checkForNullReference(dataId, "dataId");
		getBEManager().delete(dataId);
//		} catch (RuntimeException e) {
//			throw buildBefException("Delete", e);
//		}
	}

	/**
	 * 删除实体数据上指定ID的从(从)表数据，将删除变更集提交到内存。若需要将该删除变更集提交到数据库，需要在调用DeleteChild方法后，再调用Save方法。
	 * 1. 删除从表数据时，nodeCodes包含从表实体编号，hierachyIdList包含主表数据的唯一标识，ids包含要删除的从表数据的唯一标识
	 * 2. 删除从(从)表数据时，nodeCodes包含从从表所属的从表实体编号、以及从从表的实体编号；hierachyIdList包含从从表数据所属的主表数据的唯一标识，
	 * 以及从表数据的唯一标识，ids包含要删除的从从表数据的唯一标识
	 *
	 * @param nodeCodes      要删除数据的从(从)表的实体编号
	 * @param hierachyIdList 要删除数据的从(从)表的所属实体数据的唯一标识
	 * @param ids            要删除的从(从)表数据的唯一标识集合
	 */
	@Override
	public final void deleteChild(java.util.List<String> nodeCodes, java.util.List<String> hierachyIdList, java.util.List<String> ids) {
//		try {
		DataValidator.checkForNullReference(nodeCodes, "nodeCodes");
		DataValidator.checkForNullReference(hierachyIdList, "hierachyIdList");
		DataValidator.checkForNullReference(ids, "ids");

		getBEManager().deleteChild(nodeCodes, hierachyIdList, ids);
//		} catch (RuntimeException e) {
//			throw buildBefException("DeleteChild", e);
//		}
	}


	@Override
	public final RetrieveResult retrieve(List<String> dataIds) {
//		try {
		return retrieve(dataIds, new RetrieveParam());
//		} catch (RuntimeException e) {
//			throw buildBefException("Retrieve", e);
//		}
	}

	/**
	 * 批量检索
	 *
	 * @param dataIds
	 * @param retrieveParam
	 * @return
	 */
	@Override
	public final RetrieveResult retrieve(List<String> dataIds, RetrieveParam retrieveParam) {
//		try {
//			DataValidator.checkForNullReference(dataIds, "dataIds");
		Objects.requireNonNull(dataIds, "dataIds");

		return getBEManager().retrieve(dataIds, retrieveParam);
//		} catch (RuntimeException e) {
//			throw buildBefException("Retrieve", e);
//		}
	}

	@Override
	public final EditResult edit(String dataId) {
//		try {
		return getBEManager().edit(dataId);
//		} catch (RuntimeException e) {
//			throw buildBefException("Edit", e);
//		}
	}

	@Override
	public final RespectiveRetrieveResult retrieve(String dataId) {
//		try {
		RetrieveParam tempVar = new RetrieveParam();
		return retrieve(dataId, tempVar);
//		} catch (RuntimeException e) {
//			throw buildBefException("Retrieve", e);
//		}
	}

	@Override
	public final RespectiveRetrieveResult retrieve(String dataId, RetrieveParam retrieveParam) {
//		try {
//			DataValidator.checkForNullReference(dataId, "dataId");
		return getBEManager().retrieve(dataId, retrieveParam);
//		} catch (RuntimeException e) {
//			throw buildBefException("Retrieve", e);
//		}
	}

	@Override
	public final RespectiveRetrieveResult retrieveChild(java.util.List<String> nodeCodes, java.util.List<String> hierachyIdList, RetrieveParam retrieveParam) {
//		try {
		if (nodeCodes == null || nodeCodes.isEmpty()) {
			throw new NullPointerException("nodeCodes");
		}
		if (hierachyIdList == null || hierachyIdList.isEmpty()) {
			throw new NullPointerException("hierachyIdList");
		}

		return getBEManager().retrieveChild(nodeCodes, hierachyIdList, retrieveParam);
//		} catch (RuntimeException e) {
//			throw buildBefException("RetrieveChild", e);
//		}
	}

	/**
	 * 检索子表数据
	 *
	 * @param nodeCodes      除根节点外从上级到下级的节点编号
	 * @param hierachyIdList 除根节点外从上级到下级的数据ID
	 * @param retrieveParam
	 * @return
	 */
	public final RetrieveChildResult retrieveChild(java.util.List<String> nodeCodes, java.util.List<String> hierachyIdList, ArrayList<String> ids, RetrieveParam retrieveParam) {
//		try {
		if (nodeCodes == null || nodeCodes.isEmpty()) {
			throw new NullPointerException("nodeCodes");
		}
		if (hierachyIdList == null || hierachyIdList.isEmpty()) {
			throw new NullPointerException("hierachyIdList");
		}
		if (ids == null || ids.isEmpty()) {
			throw new NullPointerException("ids");
		}
		return getBEManager().retrieveChild(nodeCodes, hierachyIdList, ids, retrieveParam);
//		} catch (RuntimeException e) {
//			throw buildBefException("RetrieveChild", e);
//		}
	}

	/**
	 * 根据变更集更新数据
	 *
	 * @param changeDetail
	 */
	@Override
	public final void modify(IChangeDetail changeDetail) {
//		try {
		Objects.requireNonNull(changeDetail, "changeDetail can not be null.");
		Objects.requireNonNull(changeDetail.getDataID(), "changeDetail's DataId can not be null.");

		getBEManager().modify(changeDetail);
//		} catch (RuntimeException e) {
//			throw buildBefException("Modify", e);
//		}
	}

	@Override
	public final void modify(java.util.ArrayList<IChangeDetail> changeDetails) {
//		try {
		DataValidator.checkForNullReference(changeDetails, "changeDetails");
		getBEManager().modify(changeDetails);
//		} catch (RuntimeException e) {
//			throw buildBefException("Modify", e);
//		}
	}

	@Override
	public final void modify(EntityFilter filter, ModifyChangeDetail changeDetail) {
//		try {
		DataValidator.checkForNullReference(filter, "filter");
		DataValidator.checkForNullReference(changeDetail, "changeDetail");
		if (changeDetail.getChildChanges().size() > 0) {
			throw new IllegalArgumentException("changeDetail不支持子表变更");
		}

		getBEManager().modify(filter, changeDetail);
//		} catch (RuntimeException e) {
//			throw buildBefException("Modify", e);
//		}
	}
	@Override
	public  final List<IEntityData> queryWithoutAuthInfo(EntityFilter filter){

		return getBEManager().queryWithoutAuthInfo(filter);
	}
	@Override
	public  final List<IEntityData> queryWithoutAuthInfo(String nodeCode,EntityFilter filter){

		return getBEManager().queryWithoutAuthInfo(nodeCode,filter);
	}
	@Override
	public final List<IEntityData> query(EntityFilter filter) {
//		try {
		DataValidator.checkForNullReference(filter, "filter");
		return getBEManager().query(filter);
//		} catch (RuntimeException e) {
//			throw buildBefException("Query", e);
//		}
	}

	@Override
	public final List<IEntityData> queryWithBuffer(EntityFilter filter) {
//		try {
		DataValidator.checkForNullReference(filter, "filter");
		return getBEManager().queryWithBuffer(filter);
//		} catch (RuntimeException e) {
//			throw buildBefException("QueryWithBuffer", e);
//		}
	}

	@Override
	public final List<IEntityData> query() {
//		try {
		return query(new EntityFilter());
//		} catch (RuntimeException e) {
//			throw buildBefException("Query", e);
//		}
	}

	//ORIGINAL LINE: public List<IEntityData> query(string nodeCode, EntityFilter filter = null)
	@Override
	public final List<IEntityData> query(String nodeCode, EntityFilter filter) {
//		try {
		return getBEManager().query(nodeCode, filter);
//		} catch (RuntimeException e) {
//			throw buildBefException("Query", e);
//
//		}
	}

	//ORIGINAL LINE: public List<IEntityData> queryWithBuffer(string nodeCode, EntityFilter filter = null)
	@Override
	public final List<IEntityData> queryWithBuffer(String nodeCode, EntityFilter filter) {
//		try {
		return getBEManager().queryWithBuffer(nodeCode, filter);
//		} catch (RuntimeException e) {
//			throw buildBefException("QueryWithBuffer", e);
//
//		}
	}

	@Override
	public final int getResultCount(EntityFilter filter) {
//		try {
		if (filter.getIsUsePagination()) {
			throw new RuntimeException("查询数据数量不能带分页条件。");
		}
		return this.query(filter).size();
//		} catch (RuntimeException e) {
//			throw buildBefException("GetResultCount", e);
//		}
	}

	protected java.util.HashMap<String, String> getNodeRecord() {
		BefModelResInfoImpl modelResInfo = (BefModelResInfoImpl) getBEManager().getModelInfo();
		HashMap<String, String> map = new HashMap<>(modelResInfo.getEntityResInfos().size(), 1);
		for (EntityResInfo resInfo : modelResInfo.getEntityResInfos().values()) {
			BefEntityResInfoImpl befEntityResInfo = (BefEntityResInfoImpl) resInfo;
			map.put(befEntityResInfo.getEntityCode(), befEntityResInfo.getEntityId());
		}
		return map;
	}

	public BEFuncSessionBase createSessionItem(FuncSession session) {
		BEFuncSessionBase result = new BEFuncSessionBase(session, getBEType());
		BEManager beMgr = innerCreateBeManager();
		if (extList != null) {
			beMgr.setExtends(extList);
		}
		beMgr.setBEType(getBEType());
		beMgr.setResponseContext(result.getResponseContext());
		result.setBEManager(beMgr);
		beMgr.getBEManagerContext().setSession(session);
		beMgr.getBEManagerContext().setChangesetManager(result.getBufferChangeManager());
		beMgr.getBEManagerContext().setBufferManager(result.getBufferChangeManager());
		return result;
	}

	private IBEManager tryGetBeManager() {
		if (currentSession == null) {
			return innerCreateBeManager();
		}
		currentSession.checkValid();

		BEFuncSessionBase beFuncSession = currentSession.getFuncSessionItem(getBEType());
		if(beFuncSession==null)
			return innerCreateBeManager();
		BEManager rez = (BEManager) beFuncSession.getBEManager();
		rez.setLcpParam(param);
		return rez;
	}

	protected final IBEManager getBEManager() {
		if (currentSession == null) {
			throwNoSession();
		}
		currentSession.checkValid();

		BEFuncSessionBase beFuncSession = currentSession.getFuncSessionItem(getBEType());
		if(beFuncSession==null)
			return innerCreateBeManager();
		BEManager beManager = (BEManager) beFuncSession.getBEManager();
		beManager.setLcpParam(param);
//		beManager.getBEManagerContext().setSession(currentSession);
		return beManager;
	}

	private BEManager innerCreateBeManager() {
		BEManager beManager = (BEManager) createBEManager();
		beManager.setBEInfo(getBEInfo());
		if (extList != null) {
			beManager.setExtends(extList);
		}
		return beManager;
	}

	//region Transaction

	@Override
	public void save() {
		save(SaveParameter.getDefault());
	}

	//TODO:事务在外层service中启动, 此处改成单be类型的处理, 不启事务
	@Override
	public final void save(SaveParameter par) {
//		try {
		ILcpSaveAction action = SpringBeanUtils.getBean(ILcpSaveAction.class);
		action.execute(null, currentSession, (BEManager) this.getBEManager(), par);
//		} catch (RuntimeException e) {
//			throw buildBefException("Save", e);
//		}
	}

	@Override
	public boolean hasChanges() {
		return getBEManager().hasChanges();
	}

	@Override
	public final void cancel() {
//		try {
		ClearChangeset();
		ClearLock();
//		} catch (RuntimeException e) {
//			throw buildBefException("Cancel", e);
//		}
	}

	@Override
	public final void cleanUp() {
//		try {
		ClearChangeset();
		ClearLock();
		ClearBuffer();
//		} catch (RuntimeException e) {
//			throw buildBefException("CleanUp", e);
//		}
	}

	protected final void ClearChangeset() {
		getBEManager().clearChangeset();
	}

	protected final void ClearLock() {
		getBEManager().clearLock();
	}

	protected final void ClearBuffer() {
		getBEManager().clearBuffer();
	}

	@Override
	public final String serializeData(IEntityData data) {
//		try {
		return innerCreateBeManager().serializeData(data);
//		} catch (RuntimeException e) {
//			throw buildBefException("SerializeData", e);
//		}
	}

	@Override
	public final IEntityData deSerializeData(String data) {
//		try {
		DataValidator.checkForEmptyString(data, "data");
		return innerCreateBeManager().deSerializeData(data);
//		} catch (RuntimeException e) {
//			throw buildBefException("DeSerializeData", e);
//		}
	}

	//endregion


	//region Abstract

	protected abstract IBEManager createBEManager();

	//ORIGINAL LINE: public IEntityData createData(string dataID = "")
	@Override
	public final IEntityData createData(String dataID) {
//		try {
		return innerCreateBeManager().createData(dataID);
//		} catch (RuntimeException e) {
//			throw buildBefException("CreateData", e);
//		}
	}

	//ORIGINAL LINE: public IEntityData createChildData(string childCode, string dataID = "")
	@Override
	public final IEntityData createChildData(String childCode, String dataID) {
//		try {
		DataValidator.checkForEmptyString(childCode, "childCode");
		return innerCreateBeManager().createChildData(childCode, dataID);
//		} catch (RuntimeException e) {
//			throw buildBefException("CreateChildData", e);
//		}
	}

	@Override
	public IEntityData createUnlistenableData(String dataID) {
//		try {
		return innerCreateBeManager().createUnlistenableData(dataID);
//		} catch (RuntimeException e) {
//			throw buildBefException("CreateUnlistenableData", e);
//		}
	}

	@Override
	public IEntityData createUnlistenableChildData(String childCode, String dataID) {
//		try {
		return innerCreateBeManager().createUnlistenableChildData(childCode, dataID);
//		} catch (RuntimeException e) {
//			throw buildBefException("CreateUnlistenableChildData", e);
//		}
	}

	@Override
	public String serializeData(List<String> nodeCodes, IEntityData data) {
		throw new UnsupportedOperationException();
	}

	@Override
	public IEntityData deserializeData(List<String> nodeCodes, String serializedData) {
		throw new UnsupportedOperationException();
	}

	@Override
	public final IEntityData deserializeData(String serializedData) {
//		try {
		DataValidator.checkForEmptyString(serializedData, "serializedData");
		return innerCreateBeManager().deserializeData(serializedData);
//		} catch (RuntimeException e) {
//			throw buildBefException("DeserializeData", e);
//		}
	}

	@Override
	public final String serializeChanges(List<IChangeDetail> changes) {
//		try {
		return innerCreateBeManager().serializeChanges(changes);
//		} catch (RuntimeException e) {
//			throw buildBefException("SerializeChanges", e);
//		}
	}

	@Override
	public final List<IChangeDetail> deserializeChanges(String strChanges) {
//		try {
		DataValidator.checkForEmptyString(strChanges, "strChanges");
		return ((ICMManager) innerCreateBeManager()).deserializeChanges(strChanges);
//		} catch (RuntimeException e) {
//			throw buildBefException("DeserializeChange", e);
//		}
	}

	@Override
	public String serializeChange(IChangeDetail change) {
//		try {
		return innerCreateBeManager().serializeChange(change);
//		} catch (RuntimeException e) {
//			throw new RuntimeException("SerializeChange",e);
//		}
	}

	@Override
	public IChangeDetail deserializeChange(String changeStr) {
//		try {
		return innerCreateBeManager().deserializeChange(changeStr);
//		} catch (RuntimeException e) {
//			throw new RuntimeException("DeserializeChange",e);
//		}
	}

	/**
	 * 获取节点的ID
	 *
	 * @param nodeName 节点的编号名称
	 * @return
	 */
	@Override
	public final String getNodeId(String nodeName) {
//		try {
		if (!getNodeRecord().containsKey(nodeName)) {
			throw new RuntimeException("不存在编号为" + nodeName + "的节点");
		}
		String rez = getNodeRecord().get(nodeName);
		if (rez == null) {
			throw new RuntimeException("旧版本BE无法调用GetNodeId(nodeName)方法，如若使用，请重新编译部署");
		}
		return rez;
//		} catch (RuntimeException e) {
//			throw buildBefException("GetNodeId", e);
//		}
	}

	/**
	 * 获取主节点的ID
	 *
	 * @return
	 */
	@Override
	public final String getMainNodeId() {
//		try {
		return getNodeId(((BusinessEntity) innerCreateBeManager().createSessionlessEntity("")).getNodeCode());
//		} catch (RuntimeException e) {
//			throw buildBefException("GetMainNodeId", e);
//		}
	}

	@Override
	public final RespectiveRetrieveResult retrieve(String nodeId, String dataId, RetrieveParam retrieveParam) {
//		try {
//			DataValidator.checkForNullReference(dataId, "dataId");
		Objects.requireNonNull(dataId, "dataId");
		Objects.requireNonNull(nodeId, "nodeId");

		String mainNodeId = getMainNodeId();
		if (!nodeId.equals(mainNodeId)) {
			throw new RuntimeException("非主表暂不支持根据节点Id和dataId检索数据");
		}

		return getBEManager().retrieve(dataId, retrieveParam);
//		} catch (RuntimeException e) {
//			throw buildBefException("Retrieve", e);
//		}
	}

	@Override
	public final boolean exists(String dataId) {
//		try {
		if (DotNetToJavaStringHelper.isNullOrEmpty(dataId)) {
			throw new RuntimeException("传入dataId为空。");
		}
		RetrieveParam tempVar = new RetrieveParam();
		tempVar.setNeedLock(false);
		tempVar.setCacheType(RequestedBufferType.CurrentData);
		boolean result = getResult(dataId, tempVar);
		if (result) {
			EntityFilter entityFilter = new EntityFilter();
			FilterCondition tempVar2 = new FilterCondition();
			tempVar2.setFilterField("ID");
			tempVar2.setValue(dataId);
			entityFilter.setFilterConditions(
					new java.util.ArrayList<>(java.util.Arrays.asList(new FilterCondition[]{tempVar2})));
			return !query(entityFilter).isEmpty();
		}
		return result;
//		} catch (RuntimeException e) {
//			throw buildBefException("Exists", e);
//		}
	}

	private boolean getResult(String dataId, RetrieveParam retrieveParam) {
		return this.retrieve(dataId, retrieveParam).getData() == null ? false : true;
	}

	/**
	 * 新增getBEInfo()兼容处理
	 *
	 * @return
	 */
	protected String getBEType() {
		if (!StringUtils.isEmpty(beType)) {
			return beType;
		}
		return innerGetBEInfo().getBEType();
	}

	//运行时定制扩展be的type
	private String beType;

	@Deprecated
	public void setBeType(String beType) {
		if (StringUtils.isEmpty(beType)) {
			throw new IllegalArgumentException("beType cannot be null.");
		}
		this.beType = beType;
	}

	//运行时定制扩展be的id
	private String beId;

	public void setBEInfo(String beType, String beId) {
		Objects.requireNonNull(beType);
		Objects.requireNonNull(beId);
		this.beType = beType;
		this.beId = beId;
	}

	/**
	 * 子类继承实现
	 *
	 * @return
	 */
	protected BEInfo getBEInfo() {
		BEInfo info = innerGetBEInfo();
		if (info != null) {
			if (!StringUtils.isEmpty(beType)) {
				info.setBEType(getBEType());
			}
			if (!StringUtils.isEmpty(beId)) {
				info.setBEID(beId);
			}
		} else {
			info = new BEInfo();
			info.setBEType(getBEType());
			info.setBEID(beId);
		}
		return info;
	}

	protected BEInfo innerGetBEInfo() {
		return null;
	}

	//endregion


	//region Variable
	@Override
	public void modifyVariable(IChangeDetail change) {
		getBEManager().modifyVariable(change);
	}

//	public IVariableData Variables => ((BEManager)getBEManager()).ReadonlyVariables;

	//endregion

	@Override
	public final void generateTable(String nodeCode) {
//		try {
		getBEManager().generateTable(nodeCode);
//		} catch (RuntimeException e) {
//			throw buildBefException("GenerateTable", e);
//		}
	}

	@Override
	public final void dropTable(String nodeCode) {
//		try {
		getBEManager().dropTable(nodeCode);
//		} catch (RuntimeException e) {
//			throw buildBefException("DropTable", e);
//		}
	}

	//ORIGINAL LINE: public bool isReferred(string befConfig, string dataId, string nodeCode = "")
	@Override
	public final boolean isReferred(String befConfig, String dataId, String nodeCode) {
//		try {
		return getBEManager().isReferred(befConfig, dataId, nodeCode);
//		} catch (RuntimeException e) {
//			throw buildBefException("IsReferred", e);
//		}
	}

	private BefException buildBefException(String methodName, RuntimeException e) {
		ExceptionLevel level = ExceptionLevel.Error;

		if (e instanceof BizMessageException) {
			getResponseContext().mergeMessage(new java.util.ArrayList<>(
					java.util.Arrays.asList(new IBizMessage[]{((BizMessageException) e).getBizMessage()})));
		}
//		else if (e instanceof GSPException)
//		{
//			BizMessage tempVar = new BizMessage();
//			tempVar.MessageFormat = gspException.I18nMessage;
//			tempVar.Level = MessageLevel.Error;
//			tempVar.RuntimeException = gspException;
//			BizMessage message = tempVar;
//			getResponseContext().mergeMessage(new java.util.ArrayList<IBizMessage>(java.util.Arrays.asList(new IBizMessage[] { message})));
//			level = gspException.Level;
//		}
		else if (e instanceof CAFRuntimeException) {
			BizMessage tempVar = new BizMessage();
			tempVar.setMessageFormat(((CAFRuntimeException) e).getI18nMessage());
			tempVar.setLevel(MessageLevel.Error);
			tempVar.setException(e);
			BizMessage message = tempVar;
			getResponseContext().mergeMessage(
					new java.util.ArrayList<>(java.util.Arrays.asList(new IBizMessage[]{message})));
			level = getTransLevel(((CAFRuntimeException) e).getLevel());
		}
		return new BefException(ErrorCodes.ExcuteMgrAction, "执行'" + methodName + "'操作失败。", e, level);
	}

	private static com.inspur.edp.bef.entity.exception.ExceptionLevel getTransLevel(io.iec.edp.caf.commons.exception.ExceptionLevel level) {
		com.inspur.edp.bef.entity.exception.ExceptionLevel level1 = null;
		if (level == io.iec.edp.caf.commons.exception.ExceptionLevel.Error) {
			level1 = com.inspur.edp.bef.entity.exception.ExceptionLevel.Error;
		}

		if (level == io.iec.edp.caf.commons.exception.ExceptionLevel.Warning) {
			level1 = com.inspur.edp.bef.entity.exception.ExceptionLevel.Warning;
		}

		if (level == io.iec.edp.caf.commons.exception.ExceptionLevel.Info) {
			level1 = com.inspur.edp.bef.entity.exception.ExceptionLevel.Info;
		}

		return level1;
	}

	//TODO: 兼容be变更, 1906 response挪到sessionItem后去掉
	@Override
	public final java.util.Collection<String> getDataIds() {
		if (currentSession != null) {
			BEFuncSessionBase sessionItem = currentSession.getFuncSessionItem(getBEType());
			if (sessionItem != null && sessionItem.bizEntityCacheManager != null) {
				return sessionItem.bizEntityCacheManager.getDataIds();
			}
		}
		return new java.util.HashSet<>();
	}

	@Override
	public final void setRepositoryVariables(String key, String value) {
		getBEManager().setRepositoryVariable(key, value);
	}

	@Override
	public final boolean isEffective(String nodeCode, String dataId) {
//		try {
		return getBEManager().isEffective(nodeCode, dataId);
//		} catch (RuntimeException e) {
//			throw buildBefException("IsEffective", e);
//		}
	}

	public final boolean isDatasEffective(String nodeCode, List<String> dataIDs, RefObject<List<String>> noneEffectiveDatas) {
		return getBEManager().isDatasEffective(nodeCode, dataIDs, noneEffectiveDatas);
	}

	public final boolean isDatasEffective(String nodeCode, String propName, List<String> dataIDs, RefObject<List<String>> noneEffectiveDatas) {
		return getBEManager().isDatasEffective(nodeCode, propName, dataIDs, noneEffectiveDatas);
	}

	public IVariableData getVariables() {
		return getBEManager().getVariables();
	}

	public List<String> getDistinctFJM(String fjnPropertyName, EntityFilter filter, Integer parentLayer) {
		return getBEManager().getDistinctFJM(fjnPropertyName, filter, parentLayer);
	}

	@Override
	public void atomicallyInvoke(Runnable action) {
		Objects.requireNonNull(action);

		if (!ActionStack.isEmpty()) {
			throw new BefEngineException(ErrorCodes.InvalidSaveOperation, "不支持在自定义动作/实体动作/联动计算/校验规则中调用AtomicallyInvoke", null);
		}
//		boolean succss = true;
		Objects.requireNonNull(currentSession);
		SessionEditToken editToken = FuncSessionManager.getCurrent().beginEdit(currentSession, false);
		try {
			BufferTransactionManager instance = new BufferTransactionManager(currentSession);
			instance.Begin();
			try {
				action.run();
				if (getResponseContext().hasErrorMessage()) {
					instance.SetAbort();
				} else {
					instance.SetComplete();
				}
			} catch (Throwable e) {
				try {
					instance.SetAbort();
				} catch (Throwable ee) {
					log.error("bef内部错误:", ee);
				}
				throw e;
			}
		} finally {
			FuncSessionManager.getCurrent().endEdit(editToken);
		}
	}

	/**
	 * 获取模型相关信息
	 *
	 * @return 模型信息类
	 */
	@Override
	public ModelResInfo getModelInfo() {
		return tryGetBeManager().getModelInfo();
	}

	//region [运行时定制]扩展
	private List<IBEManagerExtend> extList;

	protected void addExtend(IBEManagerExtend ext) {
		Objects.requireNonNull(ext, "ext");

		if (extList == null) {
			extList = new ArrayList<>();
		}
		extList.add(ext);
	}
	//endregion

	@Override
	public Object executeCustomAction(String actionCode, Object... pars) {
		ActionUtil.requireNonNull(actionCode, "actionCode动作编号");
		Method[] methods = getClass().getMethods();
		Method method = null;
		for (Method item : methods) {
			if (item.getName().equals(actionCode))
				method = item;
		}
		if(method == null) {
			throw new RuntimeException("编号为["+actionCode+"]的动作不存在, 请检查编号是否正确以及元数据生成的jar正确且已部署");
		}
		try {
			return method.invoke(this, pars);
		} catch (IllegalAccessException | InvocationTargetException e) {
			throw new RuntimeException(e);
		}
	}

	//region 全量接口
	@Override
	public IEntityData retrieveDefault(IEntityData data) {
		Objects.requireNonNull(data, "data");

		return getBEManager().retrieveDefault(data);
	}

	@Override
	public void modify(IEntityData data) {
		Objects.requireNonNull(data, "data");

		getBEManager().modify(data);
	}

	@Override
	public BefTempTableContext createTempTable(List<String> nodeCodes) {
		return getBEManager().createTempTable(nodeCodes);
	}

	@Override
	public void dropTempTable(BefTempTableContext tempTableContext) {
		getBEManager().dropTempTable(tempTableContext);
	}

	@Override
	public Object createPropertyDefaultValue(String nodeCode, String propertyName) {
		return getBEManager().createPropertyDefaultValue(nodeCode, propertyName);
	}

	@Override
	public final String serializeDataForExpression(IEntityData iEntityData) {
		return getBEManager().serializeDataForExpression(iEntityData);
	}

	//region tcc
	public void tccCancel(BusinessActionContext tccContext, BefTccParamItem item)
			throws SQLException {
		((BEManager) getBEManager()).tccCancel(tccContext, item);
	}

	public void tccConfirm(BusinessActionContext tccContext, BefTccParamItem item)
			throws SQLException {
		((BEManager) getBEManager()).tccConfirm(tccContext, item);
	}
	//endregion


	@Override
	public Object generateDataId(String nodeCode) {
		return getBEManager().generateDataId(nodeCode);
	}
}
